home *** CD-ROM | disk | FTP | other *** search
- /*
- * ARTA VUMeters for Macintosh
- * Malcolm Slaney
- * Advanced Technology Group
- * Apple Computer, Inc.
- * malcolm@apple.com
- * 1992-1993
- *
- * Warranty Information
- * Even though Apple has reviewed this software, Apple makes no warranty
- * or representation, either express or implied, with respect to this
- * software, its quality, accuracy, merchantability, or fitness for a
- * particular purpose. As a result, this software is provided "as is,"
- * and you, its user, are assuming the entire risk as to its quality
- * and accuracy.
- *
- * Copyright (c) 1992-1993 by Apple Computer, Inc
- * All Rights Reserved.
- */
-
- /*
- * This application is actually implemented using three different ThinkC
- * objects.
- *
- * The most primitive is call CWindowPiece. This is just a piece of a
- * window on the screen. It comes with it's own offscreen GWorld and a
- * record of what region of the window is dirty. The idea is that a normal
- * Macintosh window can be tiled with CWindowPieces to provide all the
- * interesting graphics. This class is not specific to specific to a meter.
- * It can be used by any object that needs fast graphics on the screen.
- *
- * The CVUMeter class is a specialized kind of CWindowPiece. It knows
- * about all the things that make a VUMeter worthwhile. As such, it knows
- * how to draw a scale with ticks and labels, how to draw a pointer, and
- * where to get the latest meter reading. These objects contain off-screen
- * GWorlds for the scale (and the overall Gworld provided by the CWindowPiece.)
- *
- * The CPortWindow is a high level object that keeps track of a Macintosh
- * window and tiles one or two of the CVUMeter objects (depending on whether
- * we are displaying a mono or stereo VUMeter.).
- *
- * One helper objects is also defined.
- *
- * The CPictureMeter class is a special object that uses a PICT in the resource
- * fork to define the scale. This is only used by the "About VUMeters" dialog.
- *
- */
-
- #include <math.h>
- #include <stdio.h>
- #include "VUMeters.h"
- #include "VUMeterResources.h"
- #include <DSPManager.h>
- #include <StandardSound.h>
- #include "SoundMonitor.h"
-
- RGBColor rgbBackgroundColor = {65535, 63542, 55792}; /* Dirty Yellow */
- RGBColor rgbTickColor = {0, 0, 0}; /* Black */
- RGBColor rgbOverloadColor = {65535, 0, 0}; /* Bright Red */
- RGBColor rgbBlackColor = {0, 0, 0}; /* Black */
- RGBColor rgbWhiteColor = {65535, 65535, 65535}; /* White */
-
- #define kMeterTimeConstant .25 /* In Seconds */
-
- #define kDefaultVUWidth 200
- #define kDefaultVUHeight 90
-
- #define MIN_WINDOW_HEIGHT kDefaultVUWidth
- #define MIN_WINDOW_WIDTH kDefaultVUHeight
-
- #define DSP_MAXIMUM_VALUE (float)1.0
-
- int gPatchChannels = kMaxChannel;
- int gPortType = kInputPort;
- int gLevelType = kPeakReading;
- int gSpeedType = kNormalSpeed;
- int gReferenceType = kFullScaleReference;
-
- float gLeftInputGain = 0.0, gRightInputGain = 0.0, gMaxInputGain = 0.0;
- float gLeftOutputGain = 0.0, gRightOutputGain = 0.0, gMaxOutputGain = 0.0;
-
- /* OK, just a few more globals for
- * some state information.
- */
- MenuHandle gAppleMenu, gFileMenu, gEditMenu, gPatchMenu;
- Boolean gDone = false;
- WindowPtr gCurrentWindow = 0;
-
-
- /* A simple structure to map a small
- * integer key into a new number and
- * a Pascal string for output.
- */
- struct tagStruct {
- int num; /* Number with this key */
- int name; /* Index in STR# Resource */
- };
-
- struct tagStruct portTypes[] = {
- { SMMonitorInput, kInputPortString}, /* kInputPort */
- { SMMonitorOutput, kOutputPortString} /* kOutputPort */
- };
-
- /* Mapping between channel type
- * and the pretty name in the
- * meter window.
- */
- struct tagStruct channelTypes[] = {
- { 0, kLeftChannelString}, /* kLeftChannel */
- { 0, kRightChannelString}, /* kRightChannel */
- { 0, kMaximumChannelString}, /* kMaxChannel */
- { 0, 0} /* kBothChannel */
- };
-
- /* Mapping between level number
- * and the pretty name in the
- * meter window.
- */
- struct tagStruct levelNames[] = {
- { kPeakReading, kPeakReadingString}, /* kPeakReading */
- { kPowerReading, kPowerReadingString} /* kPowerReading */
- };
-
- /* Mapping between level number
- * and the DSP module name defined
- * in the DSP assembly language.
- */
- struct tagStruct levelModules[] = {
- { kPeakReading, kPeakModuleString}, /* kPeakReading */
- { kPowerReading, kPowerModuleString} /* kPowerReading */
- };
-
- struct tagStruct referenceNames[] = {
- { kFullScaleReference, kFullScaleString},
- { kAnalogLineReference, kAnalogLineString}
- };
-
- #define DSPMonitorNum(port, level) (port + (level * 2))
- #define MAX_DSP_MONITORS (DSPMonitorNum(kOutputPort, kPowerReading)+1)
-
- static DSPMonitor aDSPMonitor[MAX_DSP_MONITORS];
-
- int useMouseForLevels = 0;
- float gMouseLevel[2];
-
- static DSPCPUDeviceParamBlkPtr theDSP = 0;
-
- #define UNIMPL_TRAP_NUM 0x9F
- #define BOM_TRAP_NUM 0xBF5
-
- void CloseDSPs(){
- int i;
- for (i=0;i<MAX_DSP_MONITORS; i++){
- if (aDSPMonitor[i])
- SMDestroyDSPMonitor(aDSPMonitor[i]);
- aDSPMonitor[i] = 0;
- }
-
- if (theDSP)
- SMCloseDSP3210(theDSP);
- theDSP = 0;
- }
-
- static SoundStream theSoundStream = 0;
-
- float *GetDSPVolumeAddress(enum portNum portType, enum channelNum channelType,
- enum levelNum levelType, enum speedNum speedType){
- DSPMonitor theMonitor;
- Fixed frameRate, sampleRate;
- float decayRate;
-
- if (useMouseForLevels) /* Don't call DSP Manager */
- return gMouseLevel;
-
- if (NGetTrapAddress(BOM_TRAP_NUM, ToolTrap) == NGetTrapAddress(UNIMPL_TRAP_NUM, ToolTrap)){
- DoStopAlert(kConfigurationInstallError);
- ExitToShell();
- }
-
- if (theDSP == 0){
- int i;
-
- if (!theSoundStream)
- theSoundStream = SMOpenDSPSoundStream();
-
- theDSP = SMOpenDSP3210(theSoundStream);
- if (theDSP == 0){
- DoStopAlert(kConfigurationStartError);
- ExitToShell();
- }
- for (i=0;i<MAX_DSP_MONITORS; i++){
- aDSPMonitor[i] = 0;
- }
- }
-
- theMonitor = aDSPMonitor[DSPMonitorNum(portType, levelType)];
- if ( theMonitor == 0){
- Str255 moduleName;
-
- GetIndString(moduleName, METER_LABEL_RESOURCE, levelModules[levelType].name);
- theMonitor = aDSPMonitor[DSPMonitorNum(portType, levelType)] =
- SMCreateDSPMonitor(theDSP, theSoundStream,
- moduleName, portTypes[portType].num);
- if (!theMonitor){
- DoStopAlert(kCreateDSPMonitorError);
- CloseDSPs();
- ExitToShell();
- }
- }
-
- switch(channelType){
- case kLeftChannel:
- SMSetChannel(theMonitor, SMChannelAddClient, SMChannelDontChange);
- break;
- case kRightChannel:
- SMSetChannel(theMonitor, SMChannelDontChange, SMChannelAddClient);
- break;
- case kBothChannel:
- case kMaxChannel:
- SMSetChannel(theMonitor, SMChannelAddClient, SMChannelAddClient);
- break;
- }
-
- StdSndGetSampleAndFrameRate(theSoundStream, &frameRate, &sampleRate);
- decayRate=exp(-1/kMeterTimeConstant/(frameRate/65536.0));
- SMMaxSetDecayRate(theMonitor, decayRate);
- SMMaxSetScaleFactor(theMonitor, 1.0/(frameRate/65536.0));
-
- switch (speedType){
- case kFastSpeed:
- return SMGetFastLevelsPtr(theMonitor);
- default:
- return SMGetSlowLevelsPtr(theMonitor);
- }
- }
-
- void ReleaseDSPVolumeAddress(enum portNum portType, enum channelNum channelType,
- enum levelNum levelType){
- DSPMonitor theMonitor;
-
- if (useMouseForLevels) /* Short Circuit this routine. */
- return;
-
- theMonitor = aDSPMonitor[DSPMonitorNum(portType, levelType)];
- if ( theMonitor == 0){
- if (!theMonitor){
- DoStopAlert(kReleaseDSPMonitorError);
- CloseDSPs();
- ExitToShell();
- }
- }
-
- switch(channelType){
- case kLeftChannel:
- SMSetChannel(theMonitor, SMChannelRemoveClient, SMChannelDontChange);
- break;
- case kRightChannel:
- SMSetChannel(theMonitor, SMChannelDontChange, SMChannelRemoveClient);
- break;
- case kBothChannel:
- case kMaxChannel:
- SMSetChannel(theMonitor, SMChannelRemoveClient, SMChannelRemoveClient);
- break;
- }
- }
-
- void GetDSPGains(){
- unsigned long left, right;
-
- StdSndGetInputGain(theSoundStream, &left, &right);
- gLeftInputGain = -1.5*left;
- gRightInputGain = -1.5*right;
- gMaxInputGain = gLeftInputGain>gRightInputGain? gLeftInputGain : gRightInputGain;
-
- StdSndGetOutputAttenuation(theSoundStream, &left, &right);
- gLeftOutputGain = -1.5*left;
- gRightOutputGain = -1.5*right;
- gMaxOutputGain = gLeftOutputGain>gRightOutputGain? gLeftOutputGain : gRightOutputGain;
- }
-
- /****************************************** ScaleAngle *********************************/
- /*
- * The following scale angles were computed using Mathematica. Assuming that the
- * scale is logarithmic and has a total range of SCALE_DEGREES. The most positive
- * excursion (SCALE_DEGREES/2) should occur at the maximum volume level (+5) and the
- * most negative excursion (-SCALE_DEGREES/2) should occur at the minimum volume
- * level. We solve the following equation:
- * degrees = a log(dB + 65) + b
- * at the following points
- * degrees dB
- * DEG/2 +5
- * -DEG/2 -60
- * The solution is
- * a = d/(x1 - x2)
- * b = -d/2 (x1+x2)/(x1-x2)
- * where d = SCALE_DEGREES, x1 = log(10 - 5), and x2 = log(10 - -60).
- */
- float ScaleAngle(dB)
- float dB;
- {
- register float a, b, x1, x2;
- const float mindB = -60, maxdB = 5, offsetdB = 10, d = SCALE_DEGREES;
-
- if (dB < mindB)
- return -d/2;
- else if (dB > maxdB)
- return d/2;
- x1 = log(offsetdB-maxdB);
- x2 = log(offsetdB-mindB);
- a = d/(x1 - x2);
- b = -d/2*(x1 + x2)/(x1 - x2);
- return a * log(offsetdB-dB) + b;
- }
-
- /****************************************** ComputeTick *********************************/
-
- Rect ComputeTick(vu, center, length, start, stop)
- float vu;
- Point center;
- int length;
- float start, stop;
- {
- Rect r;
- float angle = ScaleAngle(vu)*3.1415926535/180.0;
- float cosAngle = cos(angle);
- float sinAngle = sin(angle);
-
- r.top = center.v - cosAngle*length*stop;
- r.bottom = center.v - cosAngle*length*start;
- r.right = center.h + sinAngle*length*start;
- r.left = center.h + sinAngle*length*stop;
-
- return r;
- }
-
- /*=================================== CWindowPiece ====================================*/
-
- void CWindowPiece::IWindowPiece(){
- fOffScreenWorld = 0;
- SetRect(&this->fWindowRect, 0, 0, 0, 0);
- fWindow = 0;
- fDirtyScreenRegion = NewRgn();
- if (!fDirtyScreenRegion){
- DoStopAlert(kScreenRegionAllocationError);
- CloseDSPs();
- ExitToShell();
- }
- }
-
- void CWindowPiece::SetWindow(WindowPtr win){
- fWindow = win;
- }
-
- void CWindowPiece::SetWindowRect(Rect *screenRect, Rect *windowRect){
- QDErr errorCode;
- GWorldPtr newWorld = 0;
-
- this->fWindowRect = *windowRect;
-
- if (fOffScreenWorld){ /* Resize Existing GWorld */
- newWorld = fOffScreenWorld;
- errorCode = UpdateGWorld(&newWorld, DEFAULT_SCREEN_DEPTH, screenRect,
- NIL_POINTER, NIL_POINTER, NO_FLAGS);
- } else { /* Allocate a new one */
-
- errorCode = NewGWorld(&newWorld, DEFAULT_SCREEN_DEPTH, screenRect, NIL_POINTER,
- NIL_POINTER, NO_FLAGS);
- }
- fOffScreenWorld = newWorld;
-
- if (errorCode == memFullErr || !IsMemoryAvailable(0)){
- DoStopAlert(kNoMemoryWindowPieceError);
- CloseDSPs();
- ExitToShell();
- }
-
- if (errorCode != noErr){
- DoStopAlert(kNoOffscreenWorldError);
- CloseDSPs();
- ExitToShell();
- }
- this->Update();
- }
-
- void CWindowPiece::Erase(){
- GDHandle oldGD;
- GWorldPtr oldGW;
-
- GetGWorld(&oldGW, &oldGD);
-
- LockPixels(fOffScreenWorld->portPixMap);
- SetGWorld(fOffScreenWorld, NIL_POINTER);
- RGBForeColor(&rgbBackgroundColor);
- EraseRect(&fWindowRect);
- SetGWorld(oldGW, oldGD);
- UnlockPixels(fOffScreenWorld->portPixMap);
- }
-
- void CWindowPiece::CopyToWindow(){
- GDHandle oldGD;
- GWorldPtr oldGW;
-
- if (!fWindow){
- DoStopAlert(kNoCopyToWindowError);
- CloseDSPs();
- ExitToShell();
- }
-
- GetGWorld(&oldGW, &oldGD);
-
- LockPixels(fOffScreenWorld->portPixMap);
- SetPort(fWindow);
-
- OffsetRgn(fDirtyScreenRegion, fWindowRect.left, fWindowRect.top);
- RGBBackColor(&rgbWhiteColor);
- RGBForeColor(&rgbBlackColor);
- CopyBits((BitMap *)&fOffScreenWorld->portPixMap, &fWindow->portBits,
- &fOffScreenWorld->portRect, &fWindowRect, srcCopy, fDirtyScreenRegion);
- OffsetRgn(fDirtyScreenRegion, -fWindowRect.left, -fWindowRect.top);
-
- SetGWorld(oldGW, oldGD);
- UnlockPixels(fOffScreenWorld->portPixMap);
- }
-
- void CWindowPiece::Dispose(){
- if (fOffScreenWorld)
- DisposeGWorld(fOffScreenWorld);
- fOffScreenWorld = 0;
- if (fDirtyScreenRegion)
- DisposeRgn(fDirtyScreenRegion);
- fDirtyScreenRegion = 0;
- /* Don't do this here... the CPortWindow
- * gets to dispose of this... don't want
- * to do this more than once!
- * if (fWindow)
- * DisposeWindow(fWindow);
- */
- fWindow = 0;
- }
-
- void CWindowPiece::Update(){
- RectRgn(fDirtyScreenRegion, &fWindowRect);
- OffsetRgn(fDirtyScreenRegion, -fWindowRect.left, -fWindowRect.top);
- }
-
- /*=================================== CVUMeter ====================================*/
-
- void CVUMeter::IVUMeter(enum portNum portType, enum channelNum channelIndicator,
- enum levelNum levelType, enum speedNum speedType,
- enum referenceNum referenceType){
- this->IWindowPiece();
- fLastReading = -1000; /* Arbitrary and unlikely */
- fScaleWorld = 0;
- SetPt(&fMeterCenter, 0, 0);
- fScaleLength = 0;
- fOverload = 0;
- fPortType = portType;
- fChannelIndicator = channelIndicator;
- fLevelType = levelType;
- fSpeedType = speedType;
- fReferenceType = referenceType;
-
- fDirtyScaleRegion = NewRgn();
- if (!fDirtyScaleRegion){
- DoStopAlert(kNoScaleRegionError);
- CloseDSPs();
- ExitToShell();
- }
-
- fCurrentReading = GetDSPVolumeAddress(fPortType, fChannelIndicator, fLevelType, fSpeedType);
- }
-
- void CVUMeter::GetExternalGain(){
- static float zeroGain = 0.0;
-
- if (fReferenceType == kAnalogLineReference){
- if (fPortType == kInputPort){
- switch (fChannelIndicator){
- case kLeftChannel:
- fChannelGainPointer = &gLeftInputGain;
- break;
- case kRightChannel:
- fChannelGainPointer = &gRightInputGain;
- break;
- case kMaxChannel:
- fChannelGainPointer = &gMaxInputGain;
- break;
- default:
- fChannelGainPointer = &zeroGain;
- }
- } else {
- switch (fChannelIndicator){
- case kLeftChannel:
- fChannelGainPointer = &gLeftOutputGain;
- break;
- case kRightChannel:
- fChannelGainPointer = &gRightOutputGain;
- break;
- case kMaxChannel:
- fChannelGainPointer = &gMaxOutputGain;
- break;
- default:
- fChannelGainPointer = &zeroGain;
- }
- }
- } else{
- fChannelGainPointer = &zeroGain;
- }
- }
-
- struct tagStruct tickList[] = {
- {-60, kMinusSixtyString},
- {-50, 0},
- {-40, kMinusFourtyString},
- {-30, kMinusThirtyString},
- {-25, 0},
- {-20, kMinusTwentyString},
- {-15, 0},
- {-10, kMinusTenString},
- {-5, kMinusFiveString},
- {-4, 0},
- {-3, 0},
- {-2, 0},
- {-1, 0},
- {0, kZeroLevelString},
- {1, 0},
- {2, 0},
- {3, 0},
- {4, 0},
- {5, kPlusFiveString}};
-
- void CVUMeter::DrawScale(){
- int i, len;
- const int kCenterRadius = 5;
- Rect rect;
- GDHandle oldGD;
- GWorldPtr oldGW;
- Str255 tickString, channelString, levelString, referenceString, minusString;
-
- if (!fScaleWorld)
- return; /* Should never see this condition...*/
-
- GetGWorld(&oldGW, &oldGD);
- LockPixels(fScaleWorld->portPixMap);
- SetGWorld(fScaleWorld, NIL_POINTER);
-
- RGBBackColor(&rgbBackgroundColor); /* Sort of dirty yellow */
- rect = fScaleWorld->portRect;
- EraseRect(&rect);
-
- RGBForeColor(&rgbOverloadColor); /* Draw Overload Bar */
- SetRect(&rect, fMeterCenter.h - fScaleLength, fMeterCenter.v - fScaleLength,
- fMeterCenter.h + fScaleLength, fMeterCenter.v + fScaleLength);
- i = fScaleLength * (kTickEnd - kTickStart) + 0.5;
- PenSize(i, i);
- FrameArc(&rect, (short)(ScaleAngle(0.0)),
- (short)(ScaleAngle(5.0)-ScaleAngle(0.0)+0.5));
-
- RGBForeColor(&rgbTickColor); /* Draw the ticks and legend */
- TextSize(SCALE_FONT_SIZE);
- TextFont(SCALE_FONT_NUMBER);
- PenSize(1,1);
- GetIndString(minusString, TICK_LABEL_RESOURCE, kMinusSignString);
-
- for (i=0;i<sizeof(tickList)/sizeof(struct tagStruct);i++){
- GetIndString(tickString, TICK_LABEL_RESOURCE, tickList[i].name);
-
- if (tickString[0] != 0)
- rect = ComputeTick(tickList[i].num, fMeterCenter, fScaleLength,
- kTickStart, kTickEnd);
- else
- rect = ComputeTick(tickList[i].num, fMeterCenter, fScaleLength,
- kTickStart, kTickMiddle);
- MoveTo(rect.right, rect.bottom);
- LineTo(rect.left, rect.top);
- if (tickString[0] != 0){
- len = StringWidth(tickString);
- /* Want to center without worrying
- * about the initial '-'. Add in
- * the width again so it won't
- * affect the centering calucation
- */
- if (minusString[0] && minusString[1] == tickString[1])
- len += StringWidth(minusString);
-
- Move(-len/2, -3); /* Center String */
- DrawString(tickString);
- }
- }
-
- /* Draw Needle Center */
- SetRect(&rect, -kCenterRadius, -kCenterRadius, kCenterRadius, kCenterRadius);
- OffsetRect(&rect, fMeterCenter.h, fMeterCenter.v);
- FrameOval(&rect);
-
- GetIndString(channelString, METER_LABEL_RESOURCE, channelTypes[fChannelIndicator].name);
- GetIndString(levelString, METER_LABEL_RESOURCE, levelNames[fLevelType].name);
- GetIndString(referenceString, METER_LABEL_RESOURCE, referenceNames[fReferenceType].name);
-
- MoveTo(5, SCALE_FONT_SIZE+2); /* Draw Channel Label */
- DrawString(channelString);
-
- if (levelNames[fLevelType].name){ /* Draw Meter Type */
- len = StringWidth(levelString);
- len += StringWidth(referenceString);
-
- i = fMeterCenter.v + kCenterRadius;
- rect = (**fScaleWorld->portPixMap).bounds;
- if (i > rect.bottom)
- i = rect.bottom;
- i -= (SCALE_FONT_SIZE*3)/2;
- MoveTo(fMeterCenter.h - len/2, i);
- DrawString(levelString);
- DrawString(referenceString);
- }
-
- if (0) { /* Add Screen Depth for Debugging */
- Str255 screenDepthString;
- NumToString(-(**((*fOffScreenWorld).portPixMap)).pixelSize, screenDepthString);
- DrawString(screenDepthString);
- }
-
- SetGWorld(oldGW, oldGD);
- UnlockPixels(fScaleWorld->portPixMap);
- }
-
- void CVUMeter::SetMeterParms(Rect *sizeRect){
- fScaleLength = (sizeRect->right - 3*SCALE_FONT_SIZE)/2;
- SetPt(&fMeterCenter, sizeRect->right/2, fScaleLength+2*SCALE_FONT_SIZE);
- }
-
- /*
- * CVUMeter::SetWindowRect - Set the size of a VUMeter. First update the size of
- * the private GWorld I use for the scale, then let the inherited method take care
- * of the offscreen GWorld.
- */
- void CVUMeter::SetWindowRect(Rect *screenRect, Rect *windowRect){
- Rect sizeRect;
- QDErr errorCode;
- GWorldPtr newWorld;
-
- sizeRect = *windowRect;
- OffsetRect(&sizeRect, -sizeRect.left, -sizeRect.top);
-
- this->SetMeterParms(&sizeRect);
-
- if (fScaleWorld){
- newWorld = fScaleWorld;
- errorCode = UpdateGWorld(&newWorld, DEFAULT_SCREEN_DEPTH, screenRect,
- NIL_POINTER, NIL_POINTER, NO_FLAGS);
- } else {
-
- errorCode = NewGWorld(&newWorld, DEFAULT_SCREEN_DEPTH, screenRect, NIL_POINTER,
- NIL_POINTER, NO_FLAGS);
- }
- fScaleWorld = newWorld;
-
- if (errorCode != noErr){
- DoCautionAlert(kCantCreateScaleWorldError);
- this->Dispose();
- return;
- }
- RectRgn(fDirtyScaleRegion, &sizeRect);
-
- inherited::SetWindowRect(screenRect, windowRect);
-
- if (!fOffScreenWorld)
- return;
-
- SetRect(&fOverloadRect,
- fOffScreenWorld->portRect.right - SCALE_OVERLOAD_DELTA - SCALE_OVERLOAD_SIZE,
- fOffScreenWorld->portRect.top + SCALE_OVERLOAD_DELTA - SCALE_OVERLOAD_SIZE,
- fOffScreenWorld->portRect.right - SCALE_OVERLOAD_DELTA + SCALE_OVERLOAD_SIZE,
- fOffScreenWorld->portRect.top + SCALE_OVERLOAD_DELTA + SCALE_OVERLOAD_SIZE);
-
- this->Update();
- this->DrawScale();
- }
-
- /*
- * This routine is responsible for combining the meter scale with the new needle's
- * position and dumping the new face into an offscreen bitmap (which is called
- * fOffscreenWorld).
- *
- * Remember, that we've already cached an offscreen bitmap with the meter's face.
- * This routine first copies in the background and the screen, then overlays the
- * meter's needle and the overload light. Finally, all the parts that have changed
- * are stored in the fDirtyScreenRegion so we know what needs updating.
- */
- void CVUMeter::DrawNeedle(){
- short currentOverload;
- GDHandle oldGD;
- GWorldPtr oldGW;
- Rect rect;
- static RgnHandle overloadRegion = 0;
-
- if (overloadRegion == 0){
- overloadRegion = NewRgn();
- }
-
-
- GetGWorld(&oldGW, &oldGD);
- LockPixels(fOffScreenWorld->portPixMap);
- LockPixels(fScaleWorld->portPixMap);
- SetGWorld(fOffScreenWorld, NIL_POINTER);
-
- RGBBackColor(&rgbWhiteColor); /* Copy in scale and bgnd. */
- RGBForeColor(&rgbBlackColor);
- CopyBits((BitMap *)&fScaleWorld->portPixMap, (BitMap *)&fOffScreenWorld->portPixMap,
- &fScaleWorld->portRect, &fOffScreenWorld->portRect, srcCopy, fDirtyScaleRegion);
-
- RGBForeColor(&rgbBlackColor); /* Be sure we are drawing in black */
- PenSize(2,2); /* Now draw the needle */
- rect = ComputeTick(fLastReading, fMeterCenter, fScaleLength, 0.0, kTickStart);
- RGBForeColor(&rgbTickColor);
- MoveTo(rect.right, rect.bottom);
- LineTo(rect.left, rect.top);
-
- if (rect.left > rect.right){
- int t;
- t = rect.left;
- rect.left = rect.right;
- rect.right = t;
- }
- /* OK, we need to take the part of the
- * scale region that is dirty (where we
- * just drew the needle into) and union
- * it with the region that has the old
- * needle in it on the screen. Be sure
- * to add some extra space to it to make
- * sure we get the full width of the line.
- */
- InsetRect(&rect, -2, -2);
- RectRgn(fDirtyScreenRegion, &rect);
- UnionRgn(fDirtyScreenRegion, fDirtyScaleRegion, fDirtyScreenRegion);
- RectRgn(fDirtyScaleRegion, &rect);
-
- currentOverload = 0;
- if (fLastReading >= 0){ /* Light the overload indicator */
- RGBForeColor(&rgbOverloadColor);
- FillOval(&fOverloadRect, black);
- currentOverload = 1;
- }
- if (currentOverload != fOverload){
- RectRgn(overloadRegion, &fOverloadRect);
- UnionRgn(fDirtyScaleRegion, overloadRegion, fDirtyScaleRegion);
- UnionRgn(fDirtyScreenRegion, overloadRegion, fDirtyScreenRegion);
- }
- fOverload = currentOverload;
-
- SetGWorld(oldGW, oldGD);
- UnlockPixels(fScaleWorld->portPixMap);
- UnlockPixels(fOffScreenWorld->portPixMap);
- }
-
- #define kNormalInputGain -11.21334612 /* 20*log10(1.1/4) */
- #define kNormalOutputGain 2.278867046 /* 20*log10(1.3/1) */
- #define kNormalPeakPowerGain 10 /* Normal Gain due to Peakiness */
-
- void CVUMeter::UpdateLevel(){
- float dB, level, left, right;
-
- switch (fChannelIndicator){
- case kRightChannel:
- case kLeftChannel:
- level = fCurrentReading[fChannelIndicator];
- break;
- default: /* Maximum of two channels */
- right = fCurrentReading[kRightChannel];
- left = fCurrentReading[kLeftChannel];
- if (left > right)
- level = left;
- else
- level = right;
- break;
- }
-
- if (!useMouseForLevels){
- if (fLevelType == kPeakReading)
- dB = 20.*log10(level/DSP_MAXIMUM_VALUE);
- else {
- dB = 10.*log10(level/DSP_MAXIMUM_VALUE/DSP_MAXIMUM_VALUE);
- dB += kNormalPeakPowerGain;
- }
-
- if (fReferenceType == kAnalogLineReference){
- if (fPortType == kInputPort)
- dB -= kNormalInputGain;
- else
- dB -= kNormalOutputGain;
- }
-
- dB += *fChannelGainPointer; /* Add in optional Singer gain */
- } else {
- dB = level;
- }
-
- if (dB != fLastReading){
- fLastReading = dB;
- this->DrawNeedle();
- this->CopyToWindow();
- }
- }
-
- void CVUMeter::RefreshLevel(){
- this->DrawNeedle();
- this->CopyToWindow();
- }
-
-
- void CVUMeter::Dispose(){
- ReleaseDSPVolumeAddress(fPortType, fChannelIndicator, fLevelType);
-
- if (fScaleWorld)
- DisposeGWorld(fScaleWorld);
- fScaleWorld = 0;
-
- if (fDirtyScaleRegion)
- DisposeRgn(fDirtyScaleRegion);
- fDirtyScaleRegion = 0;
-
- inherited::Dispose();
- }
-
- int CVUMeter::AllMemoryAllocated(){
- return fOffScreenWorld && fScaleWorld;
- }
-
- /*=================================== CPictureMeter ====================================*/
-
- void CPictureMeter::IVUMeter(enum portNum portType, enum channelNum channelType,
- enum levelNum levelType, enum speedNum speedType,
- enum referenceNum referenceType){
- PicHandle thePicture;
-
- CVUMeter::IVUMeter(portType, channelType, levelType, speedType,
- referenceType);
- thePicture = GetPicture(ABOUT_BOX_PICT_ID);
- fPicture = thePicture;
- }
-
- void CPictureMeter::DrawScale(){
- GDHandle oldGD;
- GWorldPtr oldGW;
- GWorldPtr newWorld = 0;
- Rect rect;
- short wide, high;
- OSErr errorCode;
-
- if (!fPicture || !fScaleWorld)
- return;
-
- if (!fScaleWorld)
- return; /* Should never see this condition...*/
-
- GetGWorld(&oldGW, &oldGD);
- LockPixels(fScaleWorld->portPixMap);
- rect = (*fPicture)->picFrame;
- wide = rect.right - rect.left; /* calculate width and height */
- high = rect.bottom - rect.top;
- SetRect(&rect, 0, 0, wide,high );
-
- errorCode = NewGWorld(&newWorld, 1, &rect, NIL_POINTER, NIL_POINTER, NO_FLAGS);
-
- if (errorCode == noErr){
- LockPixels(newWorld->portPixMap);
- SetGWorld(newWorld, NIL_POINTER);
- EraseRect(&newWorld->portRect);
- DrawPicture(fPicture, &rect);
-
- SetGWorld(fScaleWorld, NIL_POINTER);
- RGBBackColor(&rgbBackgroundColor); /* Sort of dirty yellow */
- EraseRect(&newWorld->portRect);
-
- CopyBits((BitMap *)&newWorld->portPixMap,
- (BitMap *)&fScaleWorld->portPixMap, &rect, &rect, srcOr, 0);
-
- DisposeGWorld(newWorld);
- } else {
- SetGWorld(fScaleWorld, NIL_POINTER);
-
- RGBBackColor(&rgbBackgroundColor); /* Sort of dirty yellow */
- rect = newWorld->portRect;
- EraseRect(&rect);
- DrawPicture(fPicture, &rect );
- }
- SetGWorld(oldGW, oldGD);
- UnlockPixels(fScaleWorld->portPixMap);
- }
-
- void CPictureMeter::SetMeterParms(Rect *sizeRect){
- Str255 theText;
- long x, y, len;
-
- GetIndString(theText, ABOUT_BOX_PICT_ID, 1);
- StringToNum(theText, &x);
- GetIndString(theText, ABOUT_BOX_PICT_ID, 2);
- StringToNum(theText, &y);
- GetIndString(theText, ABOUT_BOX_PICT_ID, 3);
- StringToNum(theText, &len);
-
- fScaleLength = len;
- SetPt(&fMeterCenter, x, y);
- }
-
- /*=================================== CPortWindow ====================================*/
-
- void CPortWindow::IPortWindow(){
- fChannel = gPatchChannels;
- fFirstMeter = fSecondMeter = 0;
- fPortType = gPortType;
- fLevelType = gLevelType;
- fSpeedType = gSpeedType;
- fReferenceType = gReferenceType;
- fWindow = 0;
- }
-
- void CPortWindow::NewWindow(){
- WindowPtr cWindow;
- Str255 windowTitle;
-
- if (fChannel == kBothChannel)
- cWindow = GetNewCWindow(BASE_RES_ID+1, NIL_POINTER, (WindowPtr)MOVE_TO_FRONT);
- else
- cWindow = GetNewCWindow(BASE_RES_ID, NIL_POINTER, (WindowPtr)MOVE_TO_FRONT);
-
- if (!cWindow){
- DoCautionAlert(kCantAllocateCWindowError);
- this->Dispose();
- return;
- }
-
- if (!IsMemoryAvailable(MemoryNeededForNewWindow(&cWindow->portRect))){
- DoCautionAlert(kCantAllocateCWindowError);
- this->Dispose();
- DisposeWindow(cWindow);
- return;
- }
-
- SetPort(cWindow);
- DrawControls(cWindow);
- #ifdef SCROLL_BARS
- DrawGrowIcon(cWindow);
- #endif
- fWindow = cWindow;
- GetIndString(windowTitle, METER_LABEL_RESOURCE, portTypes[fPortType].name);
- if (windowTitle[0])
- SetWTitle(cWindow, windowTitle);
- ShowWindow(cWindow);
- this->UpdateWindowSize();
-
- if (fFirstMeter)
- fFirstMeter->GetExternalGain();
- if (fSecondMeter)
- fSecondMeter->GetExternalGain();
- }
-
- void CPortWindow::UpdateWindowType(){
- int destroyVUs = 0;
-
- if (fChannel != gPatchChannels){
- if (gPatchChannels == kBothChannel)
- SizeWindow(fWindow, 2*kDefaultVUWidth, kDefaultVUHeight, FALSE);
- else
- SizeWindow(fWindow, kDefaultVUWidth, kDefaultVUHeight, FALSE);
- fChannel = gPatchChannels;
- destroyVUs = 1;
- }
-
- if (fLevelType != gLevelType){
- destroyVUs = 1;
- fLevelType = gLevelType;
- }
-
- if (fPortType != gPortType){
- destroyVUs = 1;
- fPortType = gPortType;
- }
-
- if (fSpeedType != gSpeedType){
- destroyVUs = 1;
- fSpeedType = gSpeedType;
- }
-
- if (fReferenceType != gReferenceType){
- destroyVUs = 1;
- fReferenceType = gReferenceType;
- }
-
- if (destroyVUs != 0){
- Str255 windowTitle;
-
- if (fFirstMeter){
- fFirstMeter->Dispose();
- delete(fFirstMeter);
- }
- if (fSecondMeter){
- fSecondMeter->Dispose();
- delete(fSecondMeter);
- }
- fFirstMeter = fSecondMeter = 0;
-
- SetPort(fWindow);
- DrawControls(fWindow);
- #ifdef SCROLL_BARS
- DrawGrowIcon(fWindow);
- #endif
- this->UpdateWindowSize();
- GetIndString(windowTitle, METER_LABEL_RESOURCE, portTypes[fPortType].name);
- if (windowTitle)
- SetWTitle(fWindow, windowTitle);
- if (fFirstMeter)
- fFirstMeter->GetExternalGain();
- if (fSecondMeter)
- fSecondMeter->GetExternalGain();
- }
- }
-
- void CPortWindow::UpdateWindowSize(){
- Rect screenRect, windowRect;
- CWindowPeek myWinPeek;
-
- myWinPeek = (CWindowPeek)fWindow;
- screenRect = (*myWinPeek->contRgn)->rgnBBox;
-
- #ifdef SCROLL_BARS
- screenRect.right -= SCROLL_BAR_SIZE; /* Actually Grow Bar Control */
- screenRect.bottom -= SCROLL_BAR_SIZE;
- #endif
- windowRect = screenRect;
- OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
-
- if (fChannel != kBothChannel){ /* Allocate a single VU Meter */
- if (!fFirstMeter){
- fFirstMeter = new(CVUMeter);
- if (!fFirstMeter){
- DoStopAlert(kCantAllocateVUMeterError);
- CloseDSPs();
- ExitToShell();
- }
- fFirstMeter->IVUMeter(fPortType, fChannel, fLevelType,
- fSpeedType, fReferenceType);
- }
- fFirstMeter->SetWindowRect(&screenRect, &windowRect);
- fFirstMeter->SetWindow(fWindow);
- if (!fFirstMeter->AllMemoryAllocated()){
- this->Dispose();
- return;
- }
- } else {
- int width = screenRect.right - screenRect.left, t;
-
- /* Allocate left VU Meter */
- screenRect.right = screenRect.left + width/2;
- windowRect.right = width/2;
-
- if (!fFirstMeter){
- fFirstMeter = new(CVUMeter);
- if (!fFirstMeter){
- DoStopAlert(kCantAllocateVUMeterError);
- CloseDSPs();
- ExitToShell();
- }
- fFirstMeter->IVUMeter(fPortType, kLeftChannel, fLevelType,
- fSpeedType, fReferenceType);
- }
- fFirstMeter->SetWindowRect(&screenRect, &windowRect);
- fFirstMeter->SetWindow(fWindow);
-
- /* Allocate right VU Meter */
- windowRect.left = width/2;
- windowRect.right = width;
- screenRect.right = screenRect.left + width;
- screenRect.left = screenRect.left + width/2;
- if (!fSecondMeter){
- fSecondMeter = new(CVUMeter);
- if (!fSecondMeter){
- DoStopAlert(kCantAllocateVUMeterError);
- CloseDSPs();
- ExitToShell();
- }
- fSecondMeter->IVUMeter(fPortType, kRightChannel, fLevelType,
- fSpeedType, fReferenceType);
- }
- fSecondMeter->SetWindowRect(&screenRect, &windowRect);
- fSecondMeter->SetWindow(fWindow);
- if (!fSecondMeter->AllMemoryAllocated()){
- this->Dispose();
- return;
- }
- }
- this->RefreshWindow();
- }
-
- void CPortWindow::UpdateLevel(){
- if (fFirstMeter)
- fFirstMeter->UpdateLevel();
-
- if (fSecondMeter)
- fSecondMeter->UpdateLevel();
- }
-
- void CPortWindow::RefreshWindow(){
- if (fFirstMeter)
- fFirstMeter->RefreshLevel();
-
- if (fSecondMeter)
- fSecondMeter->RefreshLevel();
- }
-
- WindowPtr CPortWindow::GetWindow(){
- return fWindow;
- }
-
- void CPortWindow::RedrawWindow(){
- #ifdef SCROLL_BARS
- DrawGrowIcon(fWindow);
- #endif
- if (fFirstMeter)
- fFirstMeter->CopyToWindow();
- if (fSecondMeter)
- fSecondMeter->CopyToWindow();
- }
-
- void CPortWindow::SetUpMenus(){
- CheckItem(gPatchMenu, LEFT_ITEM, fChannel == kLeftChannel);
- CheckItem(gPatchMenu, RIGHT_ITEM, fChannel == kRightChannel);
- CheckItem(gPatchMenu, BOTH_ITEM, fChannel == kBothChannel);
- CheckItem(gPatchMenu, MAXIMUM_ITEM, fChannel == kMaxChannel);
-
- CheckItem(gPatchMenu, INPUT_ITEM, fPortType == kInputPort);
- CheckItem(gPatchMenu, OUTPUT_ITEM, fPortType == kOutputPort);
-
- CheckItem(gPatchMenu, POWER_ITEM, fLevelType == kPowerReading);
- CheckItem(gPatchMenu, PEAK_ITEM, fLevelType == kPeakReading);
-
- CheckItem(gPatchMenu, FAST_ITEM, fSpeedType == kFastSpeed);
- CheckItem(gPatchMenu, NORMAL_ITEM, fSpeedType == kNormalSpeed);
-
- CheckItem(gPatchMenu, FULLSCALE_ITEM, fReferenceType == kFullScaleReference);
- CheckItem(gPatchMenu, ANALOGLINE_ITEM, fReferenceType == kAnalogLineReference);
-
- if (gCurrentWindow)
- EnableItem(gFileMenu, CLOSE_ITEM);
- else
- DisableItem(gFileMenu, CLOSE_ITEM);
- }
-
- void CPortWindow::Update(){
- if (fFirstMeter)
- fFirstMeter->Update();
- if (fSecondMeter)
- fSecondMeter->Update();
- }
-
- void CPortWindow::Dispose(){
- if (fFirstMeter){
- fFirstMeter->Dispose();
- delete(fFirstMeter);
- }
- if (fSecondMeter){
- fSecondMeter->Dispose();
- delete(fSecondMeter);
- }
- fFirstMeter = fSecondMeter = 0;
-
- if (fWindow)
- DisposeWindow(fWindow);
- fWindow = 0;
- }
-
- int CPortWindow::AllMemoryAllocated(){
- return fFirstMeter && fWindow;
- }
-
- /************************************** Entry Library ************************/
-
- #define MAX_ENTRIES 100
-
- struct objectEntry {
- long key, value;
- } objectList[MAX_ENTRIES];
-
- Boolean AddEntry(key, value)
- long key, value;
- {
- int i;
-
- for (i=0;i<MAX_ENTRIES;i++){
- if (objectList[i].key == 0){
- objectList[i].key = key;
- objectList[i].value = value;
- return true;
- }
- }
- return false;
- }
-
- long FindKey(value)
- long value;
- {
- int i;
-
- for (i=0;i<MAX_ENTRIES;i++){
- if (objectList[i].value == value)
- return objectList[i].key;
- }
- return 0;
- }
-
- long RemoveEntry(key)
- long key;
- {
- int i;
-
- for (i=0;i<MAX_ENTRIES;i++){
- if (objectList[i].key == key){
- objectList[i].key = 0;
- return;
- }
- }
- }
-
- static int entryNumber = 0;
-
- long GetNextKey(){
- int i = MAX_ENTRIES;
-
- while (i-- > 0){
- if (objectList[entryNumber].key)
- return objectList[entryNumber++].key;
- else
- entryNumber++;
- if (entryNumber >= MAX_ENTRIES)
- entryNumber = 0;
- }
- return 0;
- }
-
- /****************************************** main *********************************/
-
- #define kCheckGainMask (0x3f) /* Must be (power of two) minus 1 */
-
- main(){
- KeyMap theKeys;
- Boolean Is32Bit();
- int eventCount = 0, i;
-
- MaxApplZone();
- for (i = 0; i<20; i++) /* Lots of handles */
- MoreMasters();
-
- ToolBoxInit();
-
- MenuBarInit();
-
- GetKeys(theKeys);
- if (theKeys[1] &0x04){
- useMouseForLevels = 1;
- SysBeep(10);
- }
-
- if (!Is32Bit()){
- DoStopAlert(kNeed32BitQuickDrawError);
- } else {
- extern void MakeNewWindow();
-
- gPatchChannels = kMaxChannel;
- MakeNewWindow();
-
- while (!gDone){
- Point theLoc;
- CPortWindow *aPortWindow;
-
- if (useMouseForLevels){
- GetMouse(&theLoc);
- gMouseLevel[0] = theLoc.h;
- gMouseLevel[1] = theLoc.v;
- }
- aPortWindow = (CPortWindow *)GetNextKey();
- if (aPortWindow)
- aPortWindow->UpdateLevel();
- HandleEvent();
-
- if (!useMouseForLevels && (eventCount++ & kCheckGainMask) == 0)
- GetDSPGains();
- }
- CloseDSPs();
- }
- }
-
- #define kMemCushion (80*1024L) /* How much needed to be safe. */
-
- IsMemoryAvailable(long memoryRequest){
- long spaceAvailable;
-
- spaceAvailable = MaxBlock();
- if (spaceAvailable > kMemCushion+memoryRequest)
- return 1;
- return 0;
- }
-
- #define kTrialWindowSize 256
- #define kBytesPerPixel 5/2
-
- long MemoryNeededForNewWindow(Rect *screenRect){
- QDErr errorCode;
- GDHandle gDevice;
- long bytesNeeded;
-
- gDevice = GetMaxDevice(screenRect);
- bytesNeeded = (*((*gDevice)->gdPMap))->pixelSize;
- bytesNeeded *= (long)(screenRect->right - screenRect->left) *
- (long)(screenRect->bottom - screenRect->top) /
- 8; /* Bits per Byte */
-
- return 2 * bytesNeeded;
- }
-
- void MakeNewWindow(){
- CPortWindow *aPortWindow;
-
- if (!IsMemoryAvailable(0)){
- DoCautionAlert(kNeedMoreMemoryError);
- return;
- }
-
- if (AddEntry(0,0)){
- aPortWindow = new(CPortWindow);
- if (!aPortWindow){
- DoCautionAlert(kCantAllocateCPortWindowError);
- return;
- }
- aPortWindow->IPortWindow();
- aPortWindow->NewWindow();
-
- if (aPortWindow->AllMemoryAllocated()){
- AddEntry((long)aPortWindow, (long)aPortWindow->GetWindow());
- }
- } else {
- DoCautionAlert(kCantAllocateMoreWindowsError);
- }
- }
-
- /****************************************** ToolBoxInit *********************************/
-
- Rect gSizeRect;
-
- ToolBoxInit(){
- InitGraf(&thePort);
- InitFonts();
- FlushEvents(everyEvent, REMOVE_ALL_EVENTS);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NIL_POINTER);
- InitCursor();
-
- gSizeRect.top = MIN_WINDOW_HEIGHT;
- gSizeRect.left = MIN_WINDOW_WIDTH;
- gSizeRect.bottom = screenBits.bounds.bottom - screenBits.bounds.top;
- gSizeRect.right = screenBits.bounds.right - screenBits.bounds.left;
- }
-
- /****************************************** Is32Bit *********************************/
-
- #define QD32TRAP 0xAB03
- #define UNIMPL_TRAP 0xA89F
-
- Boolean Is32Bit(){
- SysEnvRec mySE;
-
- SysEnvirons(2,&mySE);
-
- if (!mySE.hasColorQD)
- return FALSE;
-
- return (NGetTrapAddress(QD32TRAP, ToolTrap) !=
- NGetTrapAddress(UNIMPL_TRAP, ToolTrap));
- }
-
- /****************************************** DoAlert *********************************/
-
- void DoCautionAlert(short messageNumber)
- {
- Str255 string;
-
- GetIndString(string, ALERT_STRING_RESOURCE, messageNumber);
- ParamText(string, NIL_STRING, NIL_STRING, NIL_STRING);
- CautionAlert(BASE_RES_ID, NIL_POINTER);
- }
-
- void DoStopAlert(short messageNumber)
- {
- Str255 string;
-
- GetIndString(string, ALERT_STRING_RESOURCE, messageNumber);
- ParamText(string, NIL_STRING, NIL_STRING, NIL_STRING);
- StopAlert(BASE_RES_ID, NIL_POINTER);
- }
-
- void ShowValue(short messageNumber, long val){
- Str255 messageString, valString, formatString;
-
- GetIndString(messageString, ALERT_STRING_RESOURCE, messageNumber);
- p2cstr(messageString);
-
- GetIndString(formatString, ALERT_STRING_RESOURCE, kShowValueError);
- p2cstr(formatString);
-
- sprintf((char *)valString, (char *)formatString, (char *)messageString, val);
- c2pstr((char *)valString);
-
- ParamText(valString, NIL_STRING, NIL_STRING, NIL_STRING);
- CautionAlert(BASE_RES_ID, NIL_POINTER);
- }
-
- /****************************************** MenuBarInit *********************************/
-
- MenuBarInit(){
- Handle myMenuBar;
- long size;
- int *ip;
-
- myMenuBar = GetNewMBar(BASE_RES_ID);
- if (!myMenuBar){
- DoStopAlert(kCantFindMenuBarError);
- CloseDSPs();
- ExitToShell();
- }
- SetMenuBar(myMenuBar);
-
- gAppleMenu = GetMHandle(APPLE_MENU);
- if (!gAppleMenu){
- DoStopAlert(kCantFindAppleMenuError);
- CloseDSPs();
- ExitToShell();
- }
- gFileMenu = GetMHandle(FILE_MENU);
- if (!gAppleMenu){
- DoStopAlert(kCantFindFileMenuError);
- CloseDSPs();
- ExitToShell();
- }
- gPatchMenu = GetMHandle(PATCH_MENU);
- if (!gPatchMenu){
- DoStopAlert(kCantFindPatchMenuError);
- CloseDSPs();
- ExitToShell();
- }
-
- AddResMenu(gAppleMenu, 'DRVR');
- DrawMenuBar();
- }
-
- void SetUpMenus(){
- CPortWindow *thePortWindow;
-
- if (gCurrentWindow){
- thePortWindow = (CPortWindow *)FindKey((long)gCurrentWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kMenuSetupError);
- else {
- thePortWindow->SetUpMenus();
- }
- return;
- }
- CheckItem(gPatchMenu, LEFT_ITEM, gPatchChannels == kLeftChannel);
- CheckItem(gPatchMenu, RIGHT_ITEM, gPatchChannels == kRightChannel);
- CheckItem(gPatchMenu, BOTH_ITEM, gPatchChannels == kBothChannel);
- CheckItem(gPatchMenu, MAXIMUM_ITEM, gPatchChannels == kMaxChannel);
-
- CheckItem(gPatchMenu, INPUT_ITEM, gPortType == kInputPort);
- CheckItem(gPatchMenu, OUTPUT_ITEM, gPortType == kOutputPort);
-
- CheckItem(gPatchMenu, POWER_ITEM, gLevelType == kPowerReading);
- CheckItem(gPatchMenu, PEAK_ITEM, gLevelType == kPeakReading);
-
- CheckItem(gPatchMenu, FULLSCALE_ITEM, gReferenceType == kFullScaleReference);
- CheckItem(gPatchMenu, ANALOGLINE_ITEM, gReferenceType == kAnalogLineReference);
-
- if (gCurrentWindow)
- EnableItem(gFileMenu, CLOSE_ITEM);
- else
- DisableItem(gFileMenu, CLOSE_ITEM);
- }
-
- /****************************************** HandleEvent *********************************/
-
- EventRecord gTheEvent;
-
- HandleEvent(){
- char theChar;
- CPortWindow *thePortWindow;
-
- WaitNextEvent(everyEvent, &gTheEvent, MIN_SLEEP, NIL_MOUSE_REGION);
-
- switch(gTheEvent.what){
- case nullEvent:
- break;
- case mouseDown:
- HandleMouseDown();
- break;
- case keyDown:
- case autoKey:
- theChar = gTheEvent.message & charCodeMask;
- if ((gTheEvent.modifiers & cmdKey) != 0)
- HandleMenuChoice( MenuKey(theChar));
- break;
- case updateEvt:
- BeginUpdate((WindowPtr)gTheEvent.message);
- thePortWindow = (CPortWindow *)FindKey((long)gTheEvent.message);
- if (thePortWindow){
- thePortWindow->Update();
- thePortWindow->RedrawWindow();
- } else {
- DoCautionAlert(kUpdateEventError);
- }
- EndUpdate((WindowPtr)gTheEvent.message);
- break;
- case activateEvt:
- #ifdef SCROLL_BARS
- DrawGrowIcon((WindowPtr)gTheEvent.message);
- #endif
- gCurrentWindow = (WindowPtr)gTheEvent.message;
- break;
- }
- }
-
- HandleMouseDown(){
- WindowPtr whichWindow;
- short int thePart;
- long int menuChoice, windSize;
- CPortWindow *thePortWindow;
-
- thePart = FindWindow(gTheEvent.where, &whichWindow);
- switch (thePart){
- case inMenuBar:
- SetUpMenus();
- menuChoice = MenuSelect(gTheEvent.where);
- HandleMenuChoice(menuChoice);
- break;
- case inSysWindow:
- SystemClick(&gTheEvent, whichWindow);
- break;
- case inDrag:
- DragWindow(whichWindow, gTheEvent.where, &screenBits.bounds);
-
- thePortWindow = (CPortWindow *)FindKey((long)whichWindow);
- if (!thePortWindow)
- DoCautionAlert(kInDragError);
- else
- thePortWindow->UpdateWindowSize();
- break;
- case inContent:
- SelectWindow(whichWindow);
- break;
- case inGoAway:
- thePortWindow = (CPortWindow *)FindKey((long)whichWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kGoAwayError);
- else {
- RemoveEntry((long)thePortWindow);
- thePortWindow->Dispose();
- delete(thePortWindow);
- }
-
- gCurrentWindow = 0; /* If somebody else is active
- * then they'll get an Activate
- */
- break;
- #ifdef SCROLL_BARS
- case inGrow:
- windSize = GrowWindow(whichWindow, gTheEvent.where, &gSizeRect);
- if (windSize != 0){
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(whichWindow);
- EraseRect(&whichWindow->portRect);
- SizeWindow(whichWindow, LoWord(windSize), HiWord(windSize), NORMAL_UPDATES);
- InvalRect(&whichWindow->portRect);
- SetPort(oldPort);
- }
- thePortWindow = (CPortWindow *)FindKey((long)whichWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kInGrowError);
- else {
- thePortWindow->UpdateWindowSize();
- if (!thePortWindow->AllMemoryAllocated()){
- RemoveEntry((long)thePortWindow);
- thePortWindow->Dispose();
- delete(thePortWindow);
- }
- }
- break;
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(whichWindow, gTheEvent.where, thePart)){
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(whichWindow);
- EraseRect(&whichWindow->portRect);
- ZoomWindow(whichWindow, thePart, LEAVE_WHERE_IT_IS);
- InvalRect(&whichWindow->portRect);
- SetPort(oldPort);
- }
- thePortWindow = (CPortWindow *)FindKey((long)whichWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kInZoomError);
- else {
- thePortWindow->UpdateWindowSize();
- if (!thePortWindow->AllMemoryAllocated()){
- RemoveEntry((long)thePortWindow);
- thePortWindow->Dispose();
- delete(thePortWindow);
- }
- }
- break;
- #endif /* SCROLL_BARS */
- }
- }
-
- HandleMenuChoice(menuChoice)
- long int menuChoice;
- {
- int theMenu;
- int theItem;
-
- if (menuChoice != 0){
- theMenu = HiWord(menuChoice);
- theItem = LoWord(menuChoice);
-
- switch(theMenu){
- case APPLE_MENU:
- HandleAppleChoice(theItem);
- break;
- case FILE_MENU:
- HandleFileChoice(theItem);
- break;
- case PATCH_MENU:
- HandlePatchChoice(theItem);
- break;
- default:
- /* ShowValue(kMenuChoiceError, menuChoice); */
- break;
- }
- HiliteMenu(0);
- }
- }
-
- DisplayAboutBox(){
- Rect r;
- PicHandle thePicture;
- short wide, high;
- WindowPtr wind;
- CPictureMeter *pictureMeter;
- short oldUseMouse = useMouseForLevels, waitForMouse = 1;
- float v = 0, eps=.98;
- Str255 titleString;
- long size;
-
- thePicture = GetPicture(ABOUT_BOX_PICT_ID);
-
- r = (*thePicture)->picFrame;
- wide = r.right - r.left; /* calculate width and height */
- high = r.bottom - r.top;
- SetRect(&r, 0, 0, wide,high );
- OffsetRect(&r, 100, 100);
-
- if (!IsMemoryAvailable(MemoryNeededForNewWindow(&r))){
- DoCautionAlert(kCantCreatePictureWindowError);
- return;
- }
-
- GetIndString(titleString, ALERT_STRING_RESOURCE, kAboutVUMetersString);
- wind = NewCWindow(nil, &r, titleString, TRUE, dBoxProc, (WindowPtr)-1,
- FALSE, 0);
- if (!wind){
- DoCautionAlert(kCantAllocateVUPictureError);
- return;
- }
-
- useMouseForLevels = 1;
- SetPort(wind);
- DrawControls(wind);
- ShowWindow(wind);
- pictureMeter = new(CPictureMeter);
- if (!pictureMeter){
- DoCautionAlert(kCantAllocateVUPictureError);
- return;
- }
- pictureMeter->IVUMeter(0, 0, 0, 0, 0); /* Don't care about meter types */
- OffsetRect(&r, -r.left, -r.top);
- pictureMeter->SetWindowRect(&r, &r); /* Place PictureMeter into window */
- pictureMeter->SetWindow(wind);
-
- while (waitForMouse){
- v = eps*v + (1-eps)*((Random() & 0x7f)-65);
- gMouseLevel[0] = v;
- gMouseLevel[1] = v; /* Set new random level */
- pictureMeter->UpdateLevel(); /* Redraw the meter's needle */
-
- WaitNextEvent(everyEvent, &gTheEvent, MIN_SLEEP, NIL_MOUSE_REGION);
-
- switch(gTheEvent.what){
- case mouseDown:
- waitForMouse = 0; /* Wait for a mouse click */
- break;
- default:
- break;
- }
- }
-
- pictureMeter->Dispose(); /* Cleanup things */
- DisposeWindow(wind);
- useMouseForLevels = oldUseMouse; /* Go back to normal operation */
- }
-
- HandleAppleChoice(theItem)
- int theItem;
- {
- Str255 accName;
- int accNumber;
- short itemNumber;
-
- switch (theItem){
- case ABOUT_ITEM:
- DisplayAboutBox();
- break;
- default:
- GetItem(gAppleMenu, theItem, accName);
- accNumber = OpenDeskAcc(accName);
- break;
- }
- }
-
- HandleFileChoice(theItem)
- int theItem;
- {
- CPortWindow *thePortWindow;
-
- switch (theItem){
- case NEW_ITEM:
- MakeNewWindow();
- break;
- case CLOSE_ITEM:
- if (gCurrentWindow){
- thePortWindow = (CPortWindow *)FindKey((long)gCurrentWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kCloseMenuError);
- else {
- RemoveEntry((long)thePortWindow);
- thePortWindow->Dispose();
- delete(thePortWindow);
- }
- gCurrentWindow = 0;
- }
- break;
- case QUIT_ITEM:
- gDone = true;
- break;
- }
- }
-
- HandlePatchChoice(theItem)
- int theItem;
- {
- CPortWindow *thePortWindow;
-
- switch (theItem){
- case LEFT_ITEM:
- gPatchChannels = kLeftChannel;
- break;
- case RIGHT_ITEM:
- gPatchChannels = kRightChannel;
- break;
- case MAXIMUM_ITEM:
- gPatchChannels = kMaxChannel;
- break;
- case BOTH_ITEM:
- gPatchChannels = kBothChannel;
- break;
- case INPUT_ITEM:
- gPortType = kInputPort;
- break;
- case OUTPUT_ITEM:
- gPortType = kOutputPort;
- break;
- case PEAK_ITEM:
- gLevelType = kPeakReading;
- break;
- case POWER_ITEM:
- gLevelType = kPowerReading;
- break;
- case FAST_ITEM:
- gSpeedType = kFastSpeed;
- break;
- case NORMAL_ITEM:
- gSpeedType = kNormalSpeed;
- break;
- case FULLSCALE_ITEM:
- gReferenceType = kFullScaleReference;
- break;
- case ANALOGLINE_ITEM:
- gReferenceType = kAnalogLineReference;
- break;
- default:
- return;
- }
-
- if (gCurrentWindow){
- thePortWindow = (CPortWindow *)FindKey((long)gCurrentWindow);
-
- if (!thePortWindow)
- DoCautionAlert(kPatchMenuError);
- else {
- thePortWindow->UpdateWindowType();
- if (!thePortWindow->AllMemoryAllocated()){
- RemoveEntry((long)thePortWindow);
- thePortWindow->Dispose();
- delete(thePortWindow);
- }
- }
- }
-
- }
-
-